<%
    private hasHasMany() {
        org.codehaus.groovy.grails.commons.GrailsClassUtils.getStaticPropertyValue(domainClass.clazz, 'hasMany')
    }

%><%=packageName ? "package ${packageName}\n\n" : ''%>class ${className}Controller {
    
    def index = { redirect(action:list,params:params) }

    // the delete, save and update actions only accept POST requests
    def allowedMethods = [delete:'POST', save:'POST', update:'POST']

    def list = {
        def ${propertyName} = session.search${className}
        if (!params.max && !params.order) {
            ${propertyName} = new ${className}(params.findAll({k, v -> "" != v}))
            session.search${className} = ${propertyName}
        }
        if (!params.max) params.max = 10
        [ ${propertyName}:${propertyName},
          ${propertyName}List:${className}.findAllEx(${propertyName}, params),
          total:${className}.countEx(${propertyName})]
    }

    def show = {
        def ${propertyName} = ${className}.get( params.id )

        if(!${propertyName}) {
            flash.message = "${propertyName}.not.found"
            flash.args = [params.id]
            flash.defaultMessage = "${className} not found with id \${params.id}"
            redirect(action:list)
        }
        else { return [ ${propertyName} : ${propertyName} ] }
    }

    def delete = {
        def ${propertyName} = ${className}.get( params.id )
        if(${propertyName}) {
            ${propertyName}.delete()
            flash.message = "${propertyName}.deleted"
            flash.args = [params.id]
            flash.defaultMessage = "${className} \${params.id} deleted"
            redirect(action:list)
        }
        else {
            flash.message = "${propertyName}.not.found"
            flash.args = [params.id]
            flash.defaultMessage = "${className} not found with id \${params.id}"
            redirect(action:list)
        }
    }

    def edit = {
        def ${propertyName} = ${className}.get( params.id )

        if(!${propertyName}) {
            flash.message = "${propertyName}.not.found"
            flash.args = [params.id]
            flash.defaultMessage = "${className} not found with id \${params.id}"
            redirect(action:list)
        }
        else {
            return [ ${propertyName} : ${propertyName} ]
        }
    }

    def update = {
        def ${propertyName} = ${className}.get( params.id )
<% if (hasHasMany()) { %>
        def dc = grailsApplication.getDomainClass("${className}")
        ${className}.hasMany.each { k, v ->
        	def prop = dc.getPropertyByName(k)
	        if ((prop.manyToMany && prop.owningSide) || (prop.oneToMany && !prop.otherSide)) {
	    		def otherSideClass = prop.referencedPropertyType
	    		def name = prop.name
	    		def methodName = name[0].toUpperCase() + (name.size() ? name[1..name.size() - 1] : '')
        		def ids = params."\${k}\\\$"?.id
        		ids = (ids?.class == String ? [ids] : ids?.toList()).collect({Long.valueOf(it)})
        		
   				def dels = ${propertyName}."\${k}"?.id - ids
        		def adds = ids - dels
				dels.each { id ->
					${propertyName}."removeFrom\${methodName}"(otherSideClass.get(Long.valueOf(id)))
				}
				adds.each { id ->
					${propertyName}."addTo\${methodName}"(otherSideClass.get(Long.valueOf(id)))
				}
        	}
        }
<% } %>
        if(${propertyName}) {
            ${propertyName}.properties = params
            if(!${propertyName}.hasErrors() && ${propertyName}.save()) {
                flash.message = "${propertyName}.updated"
                flash.args = [params.id]
                flash.defaultMessage = "${className} \${params.id} updated"
<% if (hasHasMany()) { %>
                ${className}.hasMany.each { k, v ->
                	def prop = dc.getPropertyByName(k)
                	if (prop.manyToMany && !prop.owningSide) {
        	    		def otherSideClass = prop.referencedPropertyType
        	    		def name = prop.otherSide.name
        	    		def methodName = name[0].toUpperCase() + name[1..name.size() - 1]
                		def ids = params."\${k}\\\$"?.id
                		ids = (ids?.class == String ? [ids] : ids?.toList()).collect({Long.valueOf(it)})
                		
           				def dels = ${propertyName}."\${k}"?.id - ids
                		def adds = ids - dels
        				dels.each { id ->
        				    otherSideClass.get(Long.valueOf(id))."removeFrom\${methodName}"(${propertyName}).save()
        				}
        				adds.each { id ->
        					otherSideClass.get(Long.valueOf(id))."addTo\${methodName}"(${propertyName}).save()
        				}
                	}
                }
<% } %>
                redirect(action:show,id:${propertyName}.id)
            }
            else {
                render(view:'edit',model:[${propertyName}:${propertyName}])
            }
        }
        else {
            flash.message = "${propertyName}.not.found"
            flash.args = [params.id]
            flash.defaultMessage = "${className} not found with id \${params.id}"
            redirect(action:edit,id:params.id)
        }
    }

    def create = {
        def ${propertyName} = new ${className}()
        ${propertyName}.properties = params
        return ['${propertyName}':${propertyName}]
    }

    def save = {
        def ${propertyName} = new ${className}(params)
<% if (hasHasMany()) { %>
        def dc = grailsApplication.getDomainClass("${className}")
        ${className}.hasMany.each { k, v ->
        	def prop = dc.getPropertyByName(k)
	        if ((prop.manyToMany && prop.owningSide) || (prop.oneToMany && !prop.otherSide)) {
	    		def otherSideClass = prop.referencedPropertyType
	    		def name = prop.name
	    		def methodName = name[0].toUpperCase() + name[1..name.size() - 1]
        		def ids = params."\${k}\\\$"?.id
        		ids = (ids?.class == String ? [ids] : ids?.toList()).collect({Long.valueOf(it)})
				ids?.each { id ->
					${propertyName}."addTo\${methodName}"(otherSideClass.get(Long.valueOf(id)))
				}
	       	}
        }
<% } %>
        if(!${propertyName}.hasErrors() && ${propertyName}.save()) {
            flash.message = "${propertyName}.created"
            flash.args = ["\${${propertyName}.id}"]
            flash.defaultMessage = "${className} \${${propertyName}.id} created"
<% if (hasHasMany()) { %>
            ${className}.hasMany.each { k, v ->
            	def prop = dc.getPropertyByName(k)
            	if (prop.manyToMany && !prop.owningSide) {
    	    		def otherSideClass = prop.referencedPropertyType
    	    		def name = prop.otherSide.name
    	    		def methodName = name[0].toUpperCase() + (name.size() ? name[1..name.size() - 1] : '')
            		def ids = params."\${k}\\\$"?.id
            		ids = (ids?.class == String ? [ids] : ids?.toList()).collect({Long.valueOf(it)})
    				ids?.each { id ->
    					otherSideClass.get(Long.valueOf(id))."addTo\${methodName}"(${propertyName}).save()
    				}
            	}
            }
<% } %>
            redirect(action:show,id:${propertyName}.id)
        }
        else {
            render(view:'create',model:[${propertyName}:${propertyName}])
        }
    }
}